#!/usr/bin/perl -w
# Set up both NFS shares and NFS mounts
# vim:tw=100 sw=2 expandtab ft=perl

# Example:
# nfs_share => {
#   '/home' => { hostname => 'rw,root_squash,no_subtree_check,async,fsid=0,crossmnt' },
#   '/r1' => { Class_Name => 'ro,root_squash,no_subtree_check,async,fsid=1,crossmnt' },
#   '/r2' => { network => 'ro,root_squash,no_subtree_check,async,fsid=2,crossmnt' },
# },
# nfs_mount => {
#   '/r1' => 'fileserver:/r1',
#   '/r2' => { path => 'fileserver:/r2', options => [ 'sync' ] },
# },

my %shares = flatten_hash(c("$hostname/nfs_share"));
if (%shares) {
  # Install NFS server packages
  package_check("nfs-common", "nfs-kernel-server") if i_distro("debian", "ubuntu");
  package_check("nfs-utils") if i_distro("redhat");

  my $restart = 0;
  my $re_export = 0;
  while (my($dir, $x) = each(%shares)) {
    my %clients;
    while (my($client, $opts) = each(%$x)) {
      my @c = expand_network($client);
      if (@c) {
        foreach my $ip (@c) {
          $clients{$ip} = $opts;
        }
      } else {
        $clients{$client} = $opts;
      }
      next;
    }

    file_append(-file => "/etc/exports",
                -add => "$dir ". join(" ", map { "$_($clients{$_})" } keys %clients),
                -match => qr/^\Q$dir/) && $re_export++;
  }

  if (-f "/etc/default/nfs-common") {
    # Debian / Ubuntu
    file_append(-file => "/etc/default/nfs-common", -add => "STATDOPTS=\"--port 4000\"",
      -match => qr/STATDOPTS=/) && $restart++;
    file_comment(-file => "/etc/default/nfs-common", -match => qr/NEED_LOCKD=/) && $restart++;
    file_modify(-file => "/etc/default/nfs-kernel-server",
                -cmd => "/etc/init.d/nfs-kernel-server restart",
                -modify => [ 's/^#?RPCMOUNTDOPTS=.*/RPCMOUNTDOPTS="--manage-gids --port 4002"/' ])
      && $restart++;
  } else {
    # RedHat
    text_install("/etc/sysconfig/nfs", <<EOF, "service nfs restart") && $restart++;
MOUNTD_PORT=4002
RQUOTAD_PORT=4003
LOCKD_TCPPORT=4001
LOCKD_UDPPORT=4001
STATD_PORT=4000
EOF
  }

  if ($restart) {
    if (-f "/etc/init.d/nfs") {
      # RHEL
      command("/etc/init.d/portmap restart");
      command("/etc/init.d/nfs restart");
      command("/etc/init.d/nfslock restart");
    } elsif (-f "/etc/init.d/nfs-common") {
      # Debian / Ubuntu
      print "Restart: $restart\n";
      command("/etc/init.d/portmap restart");
      command("/etc/init.d/nfs-common restart");
      command("/etc/init.d/nfs-kernel-server restart");
    }
  }

  command("exportfs -a") if $re_export;
}

my %mounts = flatten_hash(c("$hostname/nfs_mount"));
if (%mounts) {
  package_check("nfs-common") if i_os("debian", "ubuntu");

  while (my($dir, $x) = each(%mounts)) {
    dir_check($dir);
     my $o = (ref $x eq 'HASH') ? $x : { path => $x };
     w "No path specified for $dir" and next unless $o->{path};
     $o->{options} ||= [];
     push @{$o->{options}}, 'rw' unless grep /^r[ow]$/, @{$o->{options}};
     push @{$o->{options}}, 'async' unless grep /^a?sync$/, @{$o->{options}};
     push @{$o->{options}}, 'rsize=32768' unless grep /^rsize=/, @{$o->{options}};
     push @{$o->{options}}, 'wsize=32768' unless grep /^wsize=/, @{$o->{options}};
     push @{$o->{options}}, 'bg' unless grep /^(fg|bg)$/, @{$o->{options}};
     push @{$o->{options}}, 'hard' unless grep /^(hard|soft)$/, @{$o->{options}};
     push @{$o->{options}}, 'intr' unless grep /^(no)?intr$/, @{$o->{options}};

     file_append(-file => "/etc/fstab",
                 -add => "$o->{path} $dir nfs ". join(",", @{$o->{options}}). " 0 0" ,
                 -match => qr/\s$dir\s/,
                 -cmd => (grep /^noauto$/, @{$o->{options}}) ? "" : "mount $dir");
  }
}

